﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GBPVRX2.UiSupport;
using System.Collections;
using System.Drawing;
using GBPVRLibrary.UtilityLibrary;
using System.Text.RegularExpressions;

namespace GBPVRLibrary.ControlLibrary
{
    public class KeyPad : GuiElement
    {
        private UiStatic Background { get; set; }
        private List<UiStatic> ButtonNormal { get; set; }
        private UiStatic ButtonSelected { get; set; }

        private Hashtable BackgroundParameters { get; set; }
        private int SelectedRow { get; set; }
        private int SelectedColumn { get; set; }
        private int Rows { get; set; }
        private int Columns { get; set; }

        public bool IsPassword { get; set; }
        private bool Submitting { get; set; }

        private string _Value;
        public string Value
        {
            get{return _Value;}
            set
            {
                _Value = value;
                if (!String.IsNullOrEmpty(_Value) && AutoSubmit && _Value == CorrectCode && KeyCodeSubmitted != null)
                {
                    Submitting = true;
                    using (System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker())
                    {
                        worker.DoWork += delegate(object sender, System.ComponentModel.DoWorkEventArgs e)
                        {
                            GuiElement.NeedsRendering = true;
                            System.Threading.Thread.Sleep(500);
                            this.Visible = false;
                            this.Value = "";
                            KeyCodeSubmitted(true);
                            GuiElement.NeedsRendering = true;
                            Submitting = false;
                        };
                        worker.RunWorkerAsync();
                    }
                }
            }
        }

        private string[] Keys = "1,2,3,4,5,6,7,8,9,C,0,E".Split(',');

        private PointF ButtonsLocation { get; set; }
        private SizeF ButtonSize { get; set; }

        public delegate void KeyCodeSubmitted_EventHandler(bool Valid);
        public event KeyCodeSubmitted_EventHandler KeyCodeSubmitted;
        public string CorrectCode { get; set; }
        public bool AutoSubmit { get; set; }

        public KeyPad()
        {
            Rows = 4;
            Columns = 3;
            BackgroundParameters = new Hashtable();
            BackgroundParameters["@Value"] = this.Value;
            Background = new UiStatic(SkinHelper, "KeyPad", BackgroundParameters);

            ButtonSelected = new UiStatic(SkinHelper, "KeyPad-Button-Selected", new Hashtable());
            ButtonsLocation = SkinHelper.getPlacementAttributePos("KeyPad", "buttonsLocation");
            ButtonSize = SkinHelper.getNamedImageRelativeSize("KeyPad-Button-Normal");


            ButtonNormal = new List<UiStatic>();
            int count = 0;
            for (int r = 0; r < Rows; r++)
            {
                PointF rBounds = new PointF(this.ButtonsLocation.X, this.ButtonsLocation.Y + this.ButtonSize.Height * r);
                for (int c = 0; c < Columns; c++)
                {
                    Hashtable parameters = new Hashtable();
                    parameters["@Text"] = Keys[count];
                    UiStatic button = new UiStatic(SkinHelper, "KeyPad-Button-Normal", parameters);
                    button.SetLocation(new PointF(rBounds.X + c * this.ButtonSize.Width, rBounds.Y));
                    ButtonNormal.Add(button);                    
                    count++;
                }
            }
            this.Visible = false;
        }

        public void RequestKeyCode(string CorrectCode, string Title)
        {
            BackgroundParameters["@Title"] = Title;
            this.CorrectCode = CorrectCode;
            this.SelectedColumn = 0;
            this.SelectedRow = 0;            
            this.Value = "";
            this.Visible = true;
        }

        protected override void Render(System.Collections.ArrayList RenderList, ref bool RequiresMoreRendering)
        {
            BackgroundParameters["@Value"] = this.IsPassword ? Regex.Replace(this.Value, ".", "*") : this.Value;
            Background.SetArgs(BackgroundParameters);
            RenderList.AddRange(Background.GetRenderList());
            int count = 0;
            for (int r = 0; r < Rows; r++)
            {
                PointF rBounds = new PointF(this.ButtonsLocation.X, this.ButtonsLocation.Y + this.ButtonSize.Height * r);

                for (int c = 0; c < Columns; c++)
                {
                    if (r == SelectedRow && c == SelectedColumn)
                    {
                        Hashtable Parameters = new Hashtable();
                        Parameters["@Text"] = Keys[count];
                        ButtonSelected.SetLocation(new PointF(rBounds.X + c * this.ButtonSize.Width, rBounds.Y));
                        ButtonSelected.SetArgs(Parameters);
                        RenderList.AddRange(ButtonSelected.GetRenderList());
                    }
                    else
                    {
                        RenderList.AddRange(ButtonNormal[count].GetRenderList());
                    }

                    count++;
                }
            }
        }

        public override bool OnKeyDown(System.Windows.Forms.KeyEventArgs e)
        {
            if (Submitting)
                return true;
            switch (KeyMapper.GetControlKey(e))
            {
                case KeyMapper.ControlKey.Enter:
                    string key = Keys[(this.SelectedRow * Columns) + this.SelectedColumn];
                    if (key == "C")
                    {
                        this.Value = "";
                    }
                    else if (key == "E")
                    {
                        if (KeyCodeSubmitted != null)
                            KeyCodeSubmitted(this.Value == CorrectCode);
                        this.Visible = false;
                        this.Value = "";
                    }
                    else
                    {
                        this.Value += key;
                    }
                    return true;
                case KeyMapper.ControlKey.DirectionUp:
                    if (SelectedRow == 0)
                        SelectedRow = Rows - 1;
                    else
                        SelectedRow--;
                    return true;
                case KeyMapper.ControlKey.DirectionDown:
                    if (SelectedRow == Rows - 1)
                        SelectedRow = 0;
                    else
                        SelectedRow++;
                    return true;
                case KeyMapper.ControlKey.DirectionLeft:
                    if (SelectedColumn == 0)
                        SelectedColumn = Columns - 1;
                    else
                        SelectedColumn--;
                    return true;
                case KeyMapper.ControlKey.DirectionRight:
                    if (SelectedColumn == Columns - 1)
                        SelectedColumn = 0;
                    else
                        SelectedColumn++;
                    return true;
                case KeyMapper.ControlKey.Back:
                    this.Visible = false;
                    return true;
            }
            switch (e.KeyCode)
            {
                case System.Windows.Forms.Keys.D0:
                case System.Windows.Forms.Keys.NumPad0:
                    this.Value += "0";
                    return true;
                case System.Windows.Forms.Keys.D1:
                case System.Windows.Forms.Keys.NumPad1:
                    this.Value += "1";
                    return true;
                case System.Windows.Forms.Keys.D2:
                case System.Windows.Forms.Keys.NumPad2:
                    this.Value += "2";
                    return true;
                case System.Windows.Forms.Keys.D3:
                case System.Windows.Forms.Keys.NumPad3:
                    this.Value += "3";
                    return true;
                case System.Windows.Forms.Keys.D4:
                case System.Windows.Forms.Keys.NumPad4:
                    this.Value += "4";
                    return true;
                case System.Windows.Forms.Keys.D5:
                case System.Windows.Forms.Keys.NumPad5:
                    this.Value += "5";
                    return true;
                case System.Windows.Forms.Keys.D6:
                case System.Windows.Forms.Keys.NumPad6:
                    this.Value += "6";
                    return true;
                case System.Windows.Forms.Keys.D7:
                case System.Windows.Forms.Keys.NumPad7:
                    this.Value += "7";
                    return true;
                case System.Windows.Forms.Keys.D8:
                case System.Windows.Forms.Keys.NumPad8:
                    this.Value += "8";
                    return true;
                case System.Windows.Forms.Keys.D9:
                case System.Windows.Forms.Keys.NumPad9:
                    this.Value += "9";
                    return true;
            }
            return base.OnKeyDown(e);
        }
    }
}
